I'm after some suggestions for a quite common scenario. I have a site
where users are registered (i.e. they have a profile) and have the
option of updating their details after logging in.
I load the "update" form's controls from a User.cfc
e.g. <input type="text" name="email" id="email"
value="#oUser.getEmail()#" />
Now when the form gets submitted validation takes place and if that
validation fails the update form is reloaded with an error message.
The problem is that I want to display the new information that the
user has entered even though it hasn't yet been updated in the
database.
I feel I can't update the User objects "state" if the validation fails as the user may navigate away from the update form and as the rest of
the site depends on the User object's information this would be
potentially incorrect.
Would I be looking at some kind of memento pattern here? Some kind of
a global #request.input# struct? How do people get around this,
hopefully without complicating/messing up views with a cfparam for
each User property etc
On Wed, Sep 24, 2008 at 3:27 PM, Michael Sharman <sha...@gmail.com> wrote:
> Hi guys,
> I'm after some suggestions for a quite common scenario. I have a site > where users are registered (i.e. they have a profile) and have the > option of updating their details after logging in.
> I load the "update" form's controls from a User.cfc
> e.g. <input type="text" name="email" id="email" > value="#oUser.getEmail()#" />
> Now when the form gets submitted validation takes place and if that > validation fails the update form is reloaded with an error message. > The problem is that I want to display the new information that the > user has entered even though it hasn't yet been updated in the > database.
> I feel I can't update the User objects "state" if the validation fails > as the user may navigate away from the update form and as the rest of > the site depends on the User object's information this would be > potentially incorrect.
> Would I be looking at some kind of memento pattern here? Some kind of > a global #request.input# struct? How do people get around this, > hopefully without complicating/messing up views with a cfparam for > each User property etc
That is what I would usually do, but I'm guessing from his email that he's storing the user object in the session scope and is worried that if they don't fix their user data up, the unvalidated, unsaved data will now show on all other pages.
For example, you change your last name to Chumbawumbachumbawumbachumbawumbachumbawumba but last name has a 20 character max length. If he does session.User.save(LastName , form.LastName), the session.User.isValid() will return false, but the session.User.getLastName() used to welcome you to every page as hello FirstName LastName will show the invalid version for the rest of the session.
Michael - was that the concern you had? If so I'd consider instead of editing (what I call) the SiteUser, just load and edit a User object and then you can session.SiteUser = UserService.getByID( session.SiteUser.getID() ); to reload any changes to the site user in session scope once the new User object has been successfully validated and saved.
> Then if the object doesn't validate, I can pass it back to my view, > and it can display the invalid data just as it would do normally.
> That make sense?
> Mark
> On Wed, Sep 24, 2008 at 3:27 PM, Michael Sharman <sha...@gmail.com> > wrote:
>> Hi guys,
>> I'm after some suggestions for a quite common scenario. I have a site >> where users are registered (i.e. they have a profile) and have the >> option of updating their details after logging in.
>> I load the "update" form's controls from a User.cfc
>> e.g. <input type="text" name="email" id="email" >> value="#oUser.getEmail()#" />
>> Now when the form gets submitted validation takes place and if that >> validation fails the update form is reloaded with an error message. >> The problem is that I want to display the new information that the >> user has entered even though it hasn't yet been updated in the >> database.
>> I feel I can't update the User objects "state" if the validation >> fails >> as the user may navigate away from the update form and as the rest of >> the site depends on the User object's information this would be >> potentially incorrect.
>> Would I be looking at some kind of memento pattern here? Some kind of >> a global #request.input# struct? How do people get around this, >> hopefully without complicating/messing up views with a cfparam for >> each User property etc
On Wed, Sep 24, 2008 at 5:14 PM, Peter Bell <pb...@systemsforge.com> wrote:
> Hey Mark,
> That is what I would usually do, but I'm guessing from his email that > he's storing the user object in the session scope and is worried that > if they don't fix their user data up, the unvalidated, unsaved data > will now show on all other pages.
> For example, you change your last name to > Chumbawumbachumbawumbachumbawumbachumbawumba but last name has a 20 > character max length. If he does session.User.save(LastName , > form.LastName), the session.User.isValid() will return false, but the > session.User.getLastName() used to welcome you to every page as hello > FirstName LastName will show the invalid version for the rest of the > session.
> Michael - was that the concern you had? If so I'd consider instead of > editing (what I call) the SiteUser, just load and edit a User object > and then you can session.SiteUser = > UserService.getByID( session.SiteUser.getID() ); to reload any changes > to the site user in session scope once the new User object has been > successfully validated and saved.
> Would that work?
> Best Wishes, > Peter
> On Sep 24, 2008, at 1:56 AM, Mark Mandel wrote:
>> Where is the validation failing? At a form level, or at the object >> level?
>> Then if the object doesn't validate, I can pass it back to my view, >> and it can display the invalid data just as it would do normally.
>> That make sense?
>> Mark
>> On Wed, Sep 24, 2008 at 3:27 PM, Michael Sharman <sha...@gmail.com> >> wrote:
>>> Hi guys,
>>> I'm after some suggestions for a quite common scenario. I have a site >>> where users are registered (i.e. they have a profile) and have the >>> option of updating their details after logging in.
>>> I load the "update" form's controls from a User.cfc
>>> e.g. <input type="text" name="email" id="email" >>> value="#oUser.getEmail()#" />
>>> Now when the form gets submitted validation takes place and if that >>> validation fails the update form is reloaded with an error message. >>> The problem is that I want to display the new information that the >>> user has entered even though it hasn't yet been updated in the >>> database.
>>> I feel I can't update the User objects "state" if the validation >>> fails >>> as the user may navigate away from the update form and as the rest of >>> the site depends on the User object's information this would be >>> potentially incorrect.
>>> Would I be looking at some kind of memento pattern here? Some kind of >>> a global #request.input# struct? How do people get around this, >>> hopefully without complicating/messing up views with a cfparam for >>> each User property etc
Validation discussions frequently bring up the concept of populating beans with potentially invalid data then calling a bean.validate() function, but something doesn't quite feel right about it for me.
If I have a date field in my bean, then I would like it to be a real date value (or an empty string meaning null), or if I have a numeric field in my bean then I want it to be a real numeric value. Allowing them to be anything entered by a user just doesn't feel right - but that is just where my head is at right now.
I have been handling general add/edit forms as follows (it's a bit of a long story ...)
I create a "FormHelper" object that is aware of all fields on the form (including hidden, visible and dynamic fields). It knows how to transform database data or objects into form field values and visa versa.
For a User add/edit form I would have a UserFormHelper with some functions as follows:
* setField(name,value) * getField(name) Functions to set/get form field values.
* initialiseFields() This initialises an internal struct with all of the fields in the form. It sets each of the fields to their initial value. These values would be for "add/new" forms. This function essentially defines the fields that are permitted in the form. The field names exactly match the actual form field names. This is called from the init() function and has code that looks like:
* loadByUsedId(userId) This initialises the helper fields from the database. But this could also be something like loadByUserBean(user). This calls the setField() function for each field, but with the value from the database/bean. This is used for an "edit" form.
* loadByEvent(event) This initialises the helper fields from an "event", which is just the combined form and url scopes. This is used when attempting to save a form. The submitted form values are passed into the helper via this function.
* validate() This validates the form data. This may also populate beans and call their validate() functions, but this helper validation is aware of the entire form which may span multiple bean types. This function sets errors inside the helper.
* save() Calls validate() and if no errors, performs the save (via services/gateways). If errors during the save occur, then additional errors may be set.
<cfset helper = createObject("component","UserFormHelper").init()> <cfset helper.loadByEvent(event)> <cfset helper.save()> <cfif not helper.hasErrors()> <cfset userId = helper.getField("userId")> <cflocation url="/some/dir/index.cfm?event=editUser&userId=#userId#"> </cfif> <!--- Then display the same form again, but with error messages. The helper has a function getErrors() which returns a collection of formfield error messages. --->
The helper manages the data with the form display in mind. It holds any submitted invalid data which is redisplayed exactly as entered back onto the form when errors occur, it also prepares data for display - such as converting datetime fields from the database into the correct display values for the form. Essentially it is a representation of the form as the server sees it - without the UI - just a bunch of name/value pairs.
I have a base FormHelper that all other form helpers extend, so there is not much work in setting up new forms.
Overall this has been working out quite nicely for me, but would love to hear others ideas.
-----Original Message----- From: cfcdev@googlegroups.com [mailto:cfcdev@googlegroups.com] On Behalf Of
Michael Sharman Sent: Wednesday, 24 September 2008 3:28 PM To: CFCDev Subject: [CFCDEV] Using object "getters" after form validation fails
Hi guys,
I'm after some suggestions for a quite common scenario. I have a site where users are registered (i.e. they have a profile) and have the option of updating their details after logging in.
I load the "update" form's controls from a User.cfc
e.g. <input type="text" name="email" id="email" value="#oUser.getEmail()#" />
Now when the form gets submitted validation takes place and if that validation fails the update form is reloaded with an error message. The problem is that I want to display the new information that the user has entered even though it hasn't yet been updated in the database.
I feel I can't update the User objects "state" if the validation fails as the user may navigate away from the update form and as the rest of the site depends on the User object's information this would be potentially incorrect.
Would I be looking at some kind of memento pattern here? Some kind of a global #request.input# struct? How do people get around this, hopefully without complicating/messing up views with a cfparam for each User property etc
@Peter you are correct, I should have been a bit clearer there. The
User object is indeed stored in session and yes I am worried that
potentially "invalid" data could be displayed on other pages (as the
session.User data has been updated from the original form submission).
>If so I'd consider instead of editing (what I call) the SiteUser, just load and edit a User object >and then you can session.SiteUser = UserService.getByID( session.SiteUser.getID() ); to reload any changes
>to the site user in session scope once the new User object has been successfully validated and saved.
That could work, but I wonder if it could get too complicated with
other potential "instance" data the User object might have (site
layout, current shopping cart composed objects etc).
@Mark
>In that case, why not duplicate() (or write your own clone() method),
>on the user, and populate THAT with data? :D
Could you explain this a bit further? Ideally the following would
happen:
- Form loads with current session.User data loaded into the form controls
- User edits form and submits
- Validation fails -> View reloads with the data the user edited in
the form - BUT the session.User still retains the original data
> Validation discussions frequently bring up the concept of populating beans
> with potentially invalid data then calling a bean.validate() function, but
> something doesn't quite feel right about it for me.
> If I have a date field in my bean, then I would like it to be a real date
> value (or an empty string meaning null), or if I have a numeric field in my
> bean then I want it to be a real numeric value. Allowing them to be anything
> entered by a user just doesn't feel right - but that is just where my head
> is at right now.
> I have been handling general add/edit forms as follows (it's a bit of a long
> story ...)
> I create a "FormHelper" object that is aware of all fields on the form > (including hidden, visible and dynamic fields). It knows how to transform
> database data or objects into form field values and visa versa.
> For a User add/edit form I would have a UserFormHelper with some functions
> as follows:
> * setField(name,value)
> * getField(name)
> Functions to set/get form field values.
> * initialiseFields()
> This initialises an internal struct with all of the fields in the form. It
> sets each of the fields to their initial value. These values would be for
> "add/new" forms. This function essentially defines the fields that are
> permitted in the form. The field names exactly match the actual form field
> names. This is called from the init() function and has code that looks like:
> * loadByUsedId(userId)
> This initialises the helper fields from the database. But this could also be
> something like loadByUserBean(user). This calls the setField() function for
> each field, but with the value from the database/bean. This is used for an
> "edit" form.
> * loadByEvent(event)
> This initialises the helper fields from an "event", which is just the
> combined form and url scopes. This is used when attempting to save a form.
> The submitted form values are passed into the helper via this function.
> * validate()
> This validates the form data. This may also populate beans and call their
> validate() functions, but this helper validation is aware of the entire form > which may span multiple bean types. This function sets errors inside the
> helper.
> * save()
> Calls validate() and if no errors, performs the save (via
> services/gateways). If errors during the save occur, then additional errors
> may be set.
> Then the form display code is the same as above.
> * saveUser event:
> <cfset helper = createObject("component","UserFormHelper").init()>
> <cfset helper.loadByEvent(event)>
> <cfset helper.save()>
> <cfif not helper.hasErrors()>
> <cfset userId = helper.getField("userId")>
> <cflocation
> url="/some/dir/index.cfm?event=editUser&userId=#userId#">
> </cfif>
> <!---
> Then display the same form again, but with error messages. The helper has a
> function getErrors() which returns a collection of formfield error messages.
> --->
> The helper manages the data with the form display in mind. It holds any
> submitted invalid data which is redisplayed exactly as entered back onto the
> form when errors occur, it also prepares data for display - such as
> converting datetime fields from the database into the correct display values
> for the form. Essentially it is a representation of the form as the server
> sees it - without the UI - just a bunch of name/value pairs.
> I have a base FormHelper that all other form helpers extend, so there is not
> much work in setting up new forms.
> Overall this has been working out quite nicely for me, but would love to
> hear others ideas.
> Kevan
> -----Original Message-----
> From: cfcdev@googlegroups.com [mailto:cfcdev@googlegroups.com] On Behalf Of
> Michael Sharman
> Sent: Wednesday, 24 September 2008 3:28 PM
> To: CFCDev
> Subject: [CFCDEV] Using object "getters" after form validation fails
> Hi guys,
> I'm after some suggestions for a quite common scenario. I have a site
> where users are registered (i.e. they have a profile) and have the
> option of updating their details after logging in.
> I load the "update" form's controls from a User.cfc
> e.g. <input type="text" name="email" id="email"
> value="#oUser.getEmail()#" />
> Now when the form gets submitted validation takes place and if that
> validation fails the update form is reloaded with an error message.
> The problem is that I want to display the new information that the
> user has entered even though it hasn't yet been updated in the
> database.
> I feel I can't update the User objects "state" if the validation fails > as the user may navigate away from the update form and as the rest of
> the site depends on the User object's information this would be
> potentially incorrect.
> Would I be looking at some kind of memento pattern here? Some kind of
> a global #request.input# struct? How do people get around this,
> hopefully without complicating/messing up views with a cfparam for
> each User property etc
I have a Validator that first attempts to set the properties on the bean (I use a Transfer object that has been cloned so that the updates don't affect the real object until it is saved, but this could be done manually as well). If any properties fail to be set (argument type failure), I record those as validation errors and then move on. After the properties are set I run a validation on them to ensure that they conform to my rules (unique value, between two numbers, required, greater than/less than, etc.) and capture those as well. Only if the validator has no errors at this point do I save the object. So you don't have to type your arguments to any, you can just capture setter failures and treat them like any other validation failure.
On Wed, Sep 24, 2008 at 9:11 AM, Kevan Stannard <ke...@stannard.net.au>wrote:
> Validation discussions frequently bring up the concept of populating beans > with potentially invalid data then calling a bean.validate() function, but > something doesn't quite feel right about it for me.
> If I have a date field in my bean, then I would like it to be a real date > value (or an empty string meaning null), or if I have a numeric field in my > bean then I want it to be a real numeric value. Allowing them to be > anything > entered by a user just doesn't feel right - but that is just where my head > is at right now.
On Tue, Sep 23, 2008 at 11:27 PM, Michael Sharman <sha...@gmail.com> wrote:
> Hi guys,
> I'm after some suggestions for a quite common scenario. I have a site > where users are registered (i.e. they have a profile) and have the > option of updating their details after logging in.
> I load the "update" form's controls from a User.cfc
> e.g. <input type="text" name="email" id="email" > value="#oUser.getEmail()#" />
> Now when the form gets submitted validation takes place and if that > validation fails the update form is reloaded with an error message. > The problem is that I want to display the new information that the > user has entered even though it hasn't yet been updated in the > database.
> I feel I can't update the User objects "state" if the validation fails > as the user may navigate away from the update form and as the rest of > the site depends on the User object's information this would be > potentially incorrect.
> Would I be looking at some kind of memento pattern here? Some kind of > a global #request.input# struct? How do people get around this, > hopefully without complicating/messing up views with a cfparam for > each User property etc
On Tue, Sep 23, 2008 at 11:27 PM, Michael Sharman <sha...@gmail.com> wrote:
> Hi guys,
> I'm after some suggestions for a quite common scenario. I have a site > where users are registered (i.e. they have a profile) and have the > option of updating their details after logging in.
> I load the "update" form's controls from a User.cfc
> e.g. <input type="text" name="email" id="email" > value="#oUser.getEmail()#" />
> Now when the form gets submitted validation takes place and if that > validation fails the update form is reloaded with an error message. > The problem is that I want to display the new information that the > user has entered even though it hasn't yet been updated in the > database.
> I feel I can't update the User objects "state" if the validation fails > as the user may navigate away from the update form and as the rest of > the site depends on the User object's information this would be > potentially incorrect.
> Would I be looking at some kind of memento pattern here? Some kind of > a global #request.input# struct? How do people get around this, > hopefully without complicating/messing up views with a cfparam for > each User property etc
> layout, current shopping cart composed objects etc).
> @Mark >>In that case, why not duplicate() (or write your own clone() method), >>on the user, and populate THAT with data? :D
> Could you explain this a bit further? Ideally the following would > happen:
> - Form loads with current session.User data loaded into the form > controls > - User edits form and submits > - Validation fails -> View reloads with the data the user edited in > the form > - BUT the session.User still retains the original data
I would see the flow as (or something similar) - - put your current session.oUser in the request scope. - Form loads with <input type="text" name="email" id="email" value="#request.oUser.getEmail()#" /> - on submit duplicate() the session.oUser and put it in request scope - load in the form data into the request scope's object (the copy) - if validation fails, re-route back to the display page - page still loads with <input type="text" name="email" id="email" value="#request.oUser.getEmail()#" /> - session is still intact.
That is one solid approach. Another one (IMO no better or worse) is to type the arguments to any and to allow "invalid data" in the bean, running an isValid() on the bean to do all of the validations. There are two things I like about the typeless setters approach. One is that you can be much more granular in your error reporting, more easily. If you rely on a catch, all you really know is that the value entered wasn't a valid numeric or date. If you have a number of validations within the bean (probably composed in some kind of validator), you could be more granular in your checking and therefore in your error messages. I have come across cases where that was useful. I also personally use the bean to populate my form fields, so I can use the same code for populating the values for a first add form (using any defaults for a new bean instance), a second shot at an add (it shows exactly what you typed in - displayed in the fields again), or an edit (it shows the current values of the object). I find that works for me, but you do lose the documentation benefits of knowing what type all of your setter arguments are supposed to be. But I generate docs from my XML description of the object model (which also generates my db and synthesizes my code) and in most cases don't have the setter methods (or even the cfc's they're supposed to be in), so I gave up on making the code self documenting (as opposed to making the runtime system self documenting) a long time ago :-)
> I have a Validator that first attempts to set the properties on the > bean (I use a Transfer object that has been cloned so that the > updates don't affect the real object until it is saved, but this > could be done manually as well). If any properties fail to be set > (argument type failure), I record those as validation errors and > then move on. After the properties are set I run a validation on > them to ensure that they conform to my rules (unique value, between > two numbers, required, greater than/less than, etc.) and capture > those as well. Only if the validator has no errors at this point do > I save the object. So you don't have to type your arguments to any, > you can just capture setter failures and treat them like any other > validation failure.
> On Wed, Sep 24, 2008 at 9:11 AM, Kevan Stannard > <ke...@stannard.net.au> wrote:
> Validation discussions frequently bring up the concept of populating > beans > with potentially invalid data then calling a bean.validate() > function, but > something doesn't quite feel right about it for me.
> If I have a date field in my bean, then I would like it to be a real > date > value (or an empty string meaning null), or if I have a numeric > field in my > bean then I want it to be a real numeric value. Allowing them to be > anything > entered by a user just doesn't feel right - but that is just where > my head > is at right now.
Sure that's fine if you have control over the typing. I use Transfer which types all of the arguments automatically, so unless I manually override every single getter and setter to retype them to "any", that won't work for me. And of course, I'm not manually overriding every getter and setter. ;-) I agree that if you're writing or generating your own beans, that typing to "any" is an option.
On Fri, Sep 26, 2008 at 8:09 AM, Peter Bell <pb...@systemsforge.com> wrote: > Hi Brian, > That is one solid approach. Another one (IMO no better or worse) is to type > the arguments to any and to allow "invalid data" in the bean, running an > isValid() on the bean to do all of the validations. There are two things I > like about the typeless setters approach. One is that you can be much more > granular in your error reporting, more easily. If you rely on a catch, all > you really know is that the value entered wasn't a valid numeric or date. If > you have a number of validations within the bean (probably composed in some > kind of validator), you could be more granular in your checking and > therefore in your error messages. I have come across cases where that was > useful. I also personally use the bean to populate my form fields, so I can > use the same code for populating the values for a first add form (using any > defaults for a new bean instance), a second shot at an add (it shows exactly > what you typed in - displayed in the fields again), or an edit (it shows the > current values of the object). I find that works for me, but you do lose the > documentation benefits of knowing what type all of your setter arguments are > supposed to be. But I generate docs from my XML description of the object > model (which also generates my db and synthesizes my code) and in most cases > don't have the setter methods (or even the cfc's they're supposed to be in), > so I gave up on making the code self documenting (as opposed to making the > runtime system self documenting) a long time ago :-)
> Best Wishes, > Peter
> On Sep 24, 2008, at 12:22 PM, Brian Kotek wrote:
> I have a Validator that first attempts to set the properties on the bean (I > use a Transfer object that has been cloned so that the updates don't affect > the real object until it is saved, but this could be done manually as well). > If any properties fail to be set (argument type failure), I record those as > validation errors and then move on. After the properties are set I run a > validation on them to ensure that they conform to my rules (unique value, > between two numbers, required, greater than/less than, etc.) and capture > those as well. Only if the validator has no errors at this point do I save > the object. So you don't have to type your arguments to any, you can just > capture setter failures and treat them like any other validation failure.
> On Wed, Sep 24, 2008 at 9:11 AM, Kevan Stannard <ke...@stannard.net.au>wrote:
>> Validation discussions frequently bring up the concept of populating beans >> with potentially invalid data then calling a bean.validate() function, but >> something doesn't quite feel right about it for me.
>> If I have a date field in my bean, then I would like it to be a real date >> value (or an empty string meaning null), or if I have a numeric field in >> my >> bean then I want it to be a real numeric value. Allowing them to be >> anything >> entered by a user just doesn't feel right - but that is just where my head >> is at right now.
> Sure that's fine if you have control over the typing. I use Transfer > which types all of the arguments automatically, so unless I manually > override every single getter and setter to retype them to "any", > that won't work for me. And of course, I'm not manually overriding > every getter and setter. ;-) I agree that if you're writing or > generating your own beans, that typing to "any" is an option.
> On Fri, Sep 26, 2008 at 8:09 AM, Peter Bell <pb...@systemsforge.com> > wrote: > Hi Brian,
> That is one solid approach. Another one (IMO no better or worse) is > to type the arguments to any and to allow "invalid data" in the > bean, running an isValid() on the bean to do all of the validations. > There are two things I like about the typeless setters approach. One > is that you can be much more granular in your error reporting, more > easily. If you rely on a catch, all you really know is that the > value entered wasn't a valid numeric or date. If you have a number > of validations within the bean (probably composed in some kind of > validator), you could be more granular in your checking and > therefore in your error messages. I have come across cases where > that was useful. I also personally use the bean to populate my form > fields, so I can use the same code for populating the values for a > first add form (using any defaults for a new bean instance), a > second shot at an add (it shows exactly what you typed in - > displayed in the fields again), or an edit (it shows the current > values of the object). I find that works for me, but you do lose the > documentation benefits of knowing what type all of your setter > arguments are supposed to be. But I generate docs from my XML > description of the object model (which also generates my db and > synthesizes my code) and in most cases don't have the setter methods > (or even the cfc's they're supposed to be in), so I gave up on > making the code self documenting (as opposed to making the runtime > system self documenting) a long time ago :-)
> Best Wishes, > Peter
> On Sep 24, 2008, at 12:22 PM, Brian Kotek wrote:
>> I have a Validator that first attempts to set the properties on the >> bean (I use a Transfer object that has been cloned so that the >> updates don't affect the real object until it is saved, but this >> could be done manually as well). If any properties fail to be set >> (argument type failure), I record those as validation errors and >> then move on. After the properties are set I run a validation on >> them to ensure that they conform to my rules (unique value, between >> two numbers, required, greater than/less than, etc.) and capture >> those as well. Only if the validator has no errors at this point do >> I save the object. So you don't have to type your arguments to any, >> you can just capture setter failures and treat them like any other >> validation failure.
>> On Wed, Sep 24, 2008 at 9:11 AM, Kevan Stannard <ke...@stannard.net.au >> > wrote:
>> Validation discussions frequently bring up the concept of >> populating beans >> with potentially invalid data then calling a bean.validate() >> function, but >> something doesn't quite feel right about it for me.
>> If I have a date field in my bean, then I would like it to be a >> real date >> value (or an empty string meaning null), or if I have a numeric >> field in my >> bean then I want it to be a real numeric value. Allowing them to be >> anything >> entered by a user just doesn't feel right - but that is just where >> my head >> is at right now.
If a form field contains invalid data that cannot be set on a bean due to a type failure, how would you handle redisplaying that original invalid data back on the form again?
Thanks
Kevan
_____
From: cfcdev@googlegroups.com [mailto:cfcdev@googlegroups.com] On Behalf Of Brian Kotek Sent: Thursday, 25 September 2008 2:23 AM To: cfcdev@googlegroups.com Subject: [CFCDEV] Re: Using object "getters" after form validation fails
I have a Validator that first attempts to set the properties on the bean (I use a Transfer object that has been cloned so that the updates don't affect the real object until it is saved, but this could be done manually as well). If any properties fail to be set (argument type failure), I record those as validation errors and then move on. After the properties are set I run a validation on them to ensure that they conform to my rules (unique value, between two numbers, required, greater than/less than, etc.) and capture those as well. Only if the validator has no errors at this point do I save the object. So you don't have to type your arguments to any, you can just capture setter failures and treat them like any other validation failure.
On Wed, Sep 24, 2008 at 9:11 AM, Kevan Stannard <ke...@stannard.net.au> wrote:
Validation discussions frequently bring up the concept of populating beans with potentially invalid data then calling a bean.validate() function, but something doesn't quite feel right about it for me.
If I have a date field in my bean, then I would like it to be a real date value (or an empty string meaning null), or if I have a numeric field in my bean then I want it to be a real numeric value. Allowing them to be anything entered by a user just doesn't feel right - but that is just where my head is at right now.
Well you have two options, one, is to create another CFC that is typeless and return that. This could be done in a Generic CFC that uses onMissingMethod to store the properties and respond to getter requests. The second is to return some sort of structure of the original data along with the original User, and use that to populate the form. Basically, if you're populating the form from a CFC and you must redisplay the bad data, you either have to untype your arguments or you have to send something different back to the form so you can display the data.
On Fri, Sep 26, 2008 at 4:51 PM, Kevan Stannard <ke...@stannard.net.au>wrote:
> If a form field contains invalid data that cannot be set on a bean due to a > type failure, how would you handle redisplaying that original invalid data > back on the form again?
> Thanks
> Kevan
> ------------------------------
> *From:* cfcdev@googlegroups.com [mailto:cfcdev@googlegroups.com] *On > Behalf Of *Brian Kotek > *Sent:* Thursday, 25 September 2008 2:23 AM > *To:* cfcdev@googlegroups.com > *Subject:* [CFCDEV] Re: Using object "getters" after form validation fails
> I have a Validator that first attempts to set the properties on the bean (I > use a Transfer object that has been cloned so that the updates don't affect > the real object until it is saved, but this could be done manually as well). > If any properties fail to be set (argument type failure), I record those as > validation errors and then move on. After the properties are set I run a > validation on them to ensure that they conform to my rules (unique value, > between two numbers, required, greater than/less than, etc.) and capture > those as well. Only if the validator has no errors at this point do I save > the object. So you don't have to type your arguments to any, you can just > capture setter failures and treat them like any other validation failure.
> On Wed, Sep 24, 2008 at 9:11 AM, Kevan Stannard <ke...@stannard.net.au> > wrote:
> Validation discussions frequently bring up the concept of populating beans > with potentially invalid data then calling a bean.validate() function, but > something doesn't quite feel right about it for me.
> If I have a date field in my bean, then I would like it to be a real date > value (or an empty string meaning null), or if I have a numeric field in my > bean then I want it to be a real numeric value. Allowing them to be > anything > entered by a user just doesn't feel right - but that is just where my head > is at right now.
I have yet to come up with a solution to that problem that I'm really happy with. Currently my populate method, which loads data into the business object and validates the datatypes, takes any invalid values and stores them in "shadow" properties, from which I can retrieve them when I need to display them. Unfortunately this technique requires a custom getter for any properties that could have invalid values (most are strings, so they don't need this functionality). Another way around this is to use a generic getter that checks for the existence of an invalid shadow property, and calls the standard getter if no invalid value has been stored. But I'm not too keen on that either.
So, my solution works, allows me to use my business object directly in my view (e.g., myObj.getName()), and also allows me to redisplay any invalid values entered by a user, but I'm just not that keen on the implementation. I hope to one day either hear of a better implementation or come up with something on my own.
On Fri, Sep 26, 2008 at 4:51 PM, Kevan Stannard <ke...@stannard.net.au> wrote: > Hi Brian, Mark
> If a form field contains invalid data that cannot be set on a bean due to a > type failure, how would you handle redisplaying that original invalid data > back on the form again?
> Thanks
> Kevan
> ________________________________
> From: cfcdev@googlegroups.com [mailto:cfcdev@googlegroups.com] On Behalf Of > Brian Kotek > Sent: Thursday, 25 September 2008 2:23 AM > To: cfcdev@googlegroups.com > Subject: [CFCDEV] Re: Using object "getters" after form validation fails
> I have a Validator that first attempts to set the properties on the bean (I > use a Transfer object that has been cloned so that the updates don't affect > the real object until it is saved, but this could be done manually as well). > If any properties fail to be set (argument type failure), I record those as > validation errors and then move on. After the properties are set I run a > validation on them to ensure that they conform to my rules (unique value, > between two numbers, required, greater than/less than, etc.) and capture > those as well. Only if the validator has no errors at this point do I save > the object. So you don't have to type your arguments to any, you can just > capture setter failures and treat them like any other validation failure.
> On Wed, Sep 24, 2008 at 9:11 AM, Kevan Stannard <ke...@stannard.net.au> > wrote:
> Validation discussions frequently bring up the concept of populating beans > with potentially invalid data then calling a bean.validate() function, but > something doesn't quite feel right about it for me.
> If I have a date field in my bean, then I would like it to be a real date > value (or an empty string meaning null), or if I have a numeric field in my > bean then I want it to be a real numeric value. Allowing them to be anything > entered by a user just doesn't feel right - but that is just where my head > is at right now.
I spent some time discussing this with Paul Marcotte last week and we came up with an idea that I think is similar to what Brian was suggesting. Here's what we came up with:
Keep business object exactly as it is, with typed getters and setters. Include the "shadow property" logic to store invalid data that cannot be stored by a setter. As the business object is created by a business object factory, wrap the business object in a generic wrapper. That wrapper would use onMM to pass all setters to the underlying business object, and to allow all getters to first check for a shadow property and if one does not exist, then pass the getter to the underlying business object.
This would allow one to keep the API of the business object, without having to resort to generic getters and setters, but would remove the previous requirement (in my implementation) of having to write a custom getter for any properties that need to be able to store invalid data. You could then use your business object directly in your view and would always get back the data that the user submitted, valid or not.
I haven't actually written this yet (I will), but in theory it sounds pretty good.
<bob.silverb...@gmail.com> wrote: > I have yet to come up with a solution to that problem that I'm really > happy with. Currently my populate method, which loads data into the > business object and validates the datatypes, takes any invalid values > and stores them in "shadow" properties, from which I can retrieve them > when I need to display them. Unfortunately this technique requires a > custom getter for any properties that could have invalid values (most > are strings, so they don't need this functionality). Another way > around this is to use a generic getter that checks for the existence > of an invalid shadow property, and calls the standard getter if no > invalid value has been stored. But I'm not too keen on that either.
> So, my solution works, allows me to use my business object directly in > my view (e.g., myObj.getName()), and also allows me to redisplay any > invalid values entered by a user, but I'm just not that keen on the > implementation. I hope to one day either hear of a better > implementation or come up with something on my own.
> On Fri, Sep 26, 2008 at 4:51 PM, Kevan Stannard <ke...@stannard.net.au> wrote: >> Hi Brian, Mark
>> If a form field contains invalid data that cannot be set on a bean due to a >> type failure, how would you handle redisplaying that original invalid data >> back on the form again?
>> Thanks
>> Kevan
>> ________________________________
>> From: cfcdev@googlegroups.com [mailto:cfcdev@googlegroups.com] On Behalf Of >> Brian Kotek >> Sent: Thursday, 25 September 2008 2:23 AM >> To: cfcdev@googlegroups.com >> Subject: [CFCDEV] Re: Using object "getters" after form validation fails
>> I have a Validator that first attempts to set the properties on the bean (I >> use a Transfer object that has been cloned so that the updates don't affect >> the real object until it is saved, but this could be done manually as well). >> If any properties fail to be set (argument type failure), I record those as >> validation errors and then move on. After the properties are set I run a >> validation on them to ensure that they conform to my rules (unique value, >> between two numbers, required, greater than/less than, etc.) and capture >> those as well. Only if the validator has no errors at this point do I save >> the object. So you don't have to type your arguments to any, you can just >> capture setter failures and treat them like any other validation failure.
>> On Wed, Sep 24, 2008 at 9:11 AM, Kevan Stannard <ke...@stannard.net.au> >> wrote:
>> Validation discussions frequently bring up the concept of populating beans >> with potentially invalid data then calling a bean.validate() function, but >> something doesn't quite feel right about it for me.
>> If I have a date field in my bean, then I would like it to be a real date >> value (or an empty string meaning null), or if I have a numeric field in my >> bean then I want it to be a real numeric value. Allowing them to be anything >> entered by a user just doesn't feel right - but that is just where my head >> is at right now.
Just to confirm, you clone a copy of the transfer object and then attempt to set each of the properties with a <cftry><cfcatch> around it so if any of the properties fails to set you note it, and if no errors were detected you make a second pass at each property for the additional rules? If any errors were detected on either pass you return the cloned object to the form to re-populate the form. If no errors were detected, save the cloned transfer object, if saved successfully, update your original object from the clone?
Sorry if that is a little incoherent, but I want to make sure I am following you from form submission and back to the form if errors occur, and if not, persisting to the DB. I have read the other posts in the group here regarding changing the type to "Any" or not and I think that is what you were addressing here. Also the issue of making sure the session scope object in in sync as to what is in the DB.
On Wed, Sep 24, 2008 at 12:22 PM, Brian Kotek <brian...@gmail.com> wrote: > I have a Validator that first attempts to set the properties on the bean (I > use a Transfer object that has been cloned so that the updates don't affect > the real object until it is saved, but this could be done manually as well). > If any properties fail to be set (argument type failure), I record those as > validation errors and then move on. After the properties are set I run a > validation on them to ensure that they conform to my rules (unique value, > between two numbers, required, greater than/less than, etc.) and capture > those as well. Only if the validator has no errors at this point do I save > the object. So you don't have to type your arguments to any, you can just > capture setter failures and treat them like any other validation failure.
On Thu, Oct 2, 2008 at 9:31 AM, Bob Silverberg <bob.silverb...@gmail.com> wrote:
> I spent some time discussing this with Paul Marcotte last week and we > came up with an idea that I think is similar to what Brian was > suggesting. Here's what we came up with:
> Keep business object exactly as it is, with typed getters and setters. > Include the "shadow property" logic to store invalid data that cannot > be stored by a setter. As the business object is created by a > business object factory, wrap the business object in a generic > wrapper. That wrapper would use onMM to pass all setters to the > underlying business object, and to allow all getters to first check > for a shadow property and if one does not exist, then pass the getter > to the underlying business object.
> This would allow one to keep the API of the business object, without > having to resort to generic getters and setters, but would remove the > previous requirement (in my implementation) of having to write a > custom getter for any properties that need to be able to store invalid > data. You could then use your business object directly in your view > and would always get back the data that the user submitted, valid or > not.
> I haven't actually written this yet (I will), but in theory it sounds > pretty good.
> Comments?
> On Fri, Sep 26, 2008 at 5:08 PM, Bob Silverberg > <bob.silverb...@gmail.com> wrote: >> I have yet to come up with a solution to that problem that I'm really >> happy with. Currently my populate method, which loads data into the >> business object and validates the datatypes, takes any invalid values >> and stores them in "shadow" properties, from which I can retrieve them >> when I need to display them. Unfortunately this technique requires a >> custom getter for any properties that could have invalid values (most >> are strings, so they don't need this functionality). Another way >> around this is to use a generic getter that checks for the existence >> of an invalid shadow property, and calls the standard getter if no >> invalid value has been stored. But I'm not too keen on that either.
>> So, my solution works, allows me to use my business object directly in >> my view (e.g., myObj.getName()), and also allows me to redisplay any >> invalid values entered by a user, but I'm just not that keen on the >> implementation. I hope to one day either hear of a better >> implementation or come up with something on my own.
>> On Fri, Sep 26, 2008 at 4:51 PM, Kevan Stannard <ke...@stannard.net.au> wrote: >>> Hi Brian, Mark
>>> If a form field contains invalid data that cannot be set on a bean due to a >>> type failure, how would you handle redisplaying that original invalid data >>> back on the form again?
>>> Thanks
>>> Kevan
>>> ________________________________
>>> From: cfcdev@googlegroups.com [mailto:cfcdev@googlegroups.com] On Behalf Of >>> Brian Kotek >>> Sent: Thursday, 25 September 2008 2:23 AM >>> To: cfcdev@googlegroups.com >>> Subject: [CFCDEV] Re: Using object "getters" after form validation fails
>>> I have a Validator that first attempts to set the properties on the bean (I >>> use a Transfer object that has been cloned so that the updates don't affect >>> the real object until it is saved, but this could be done manually as well). >>> If any properties fail to be set (argument type failure), I record those as >>> validation errors and then move on. After the properties are set I run a >>> validation on them to ensure that they conform to my rules (unique value, >>> between two numbers, required, greater than/less than, etc.) and capture >>> those as well. Only if the validator has no errors at this point do I save >>> the object. So you don't have to type your arguments to any, you can just >>> capture setter failures and treat them like any other validation failure.
>>> On Wed, Sep 24, 2008 at 9:11 AM, Kevan Stannard <ke...@stannard.net.au> >>> wrote:
>>> Validation discussions frequently bring up the concept of populating beans >>> with potentially invalid data then calling a bean.validate() function, but >>> something doesn't quite feel right about it for me.
>>> If I have a date field in my bean, then I would like it to be a real date >>> value (or an empty string meaning null), or if I have a numeric field in my >>> bean then I want it to be a real numeric value. Allowing them to be anything >>> entered by a user just doesn't feel right - but that is just where my head >>> is at right now.
I tried it and it worked like a charm. In fact, I have incorporated it into a "validations framework" that I've been working on for the past several weeks. I will be discussing and documenting the framework on my blog over the next while, and hope to have a demo up any day now. So far I've just written an introductory post about the goals of the framework. If you're interested you can find that post here:
On Thu, Oct 9, 2008 at 2:59 PM, Dan O'Keefe <dan.oke...@gmail.com> wrote:
> Bob,
> Was wondering if you gave this idea a spin and have prototyped it - > and if so, did it work as expected for you.
> Thanks,
> Dan
> On Thu, Oct 2, 2008 at 9:31 AM, Bob Silverberg <bob.silverb...@gmail.com> wrote:
>> I spent some time discussing this with Paul Marcotte last week and we >> came up with an idea that I think is similar to what Brian was >> suggesting. Here's what we came up with:
>> Keep business object exactly as it is, with typed getters and setters. >> Include the "shadow property" logic to store invalid data that cannot >> be stored by a setter. As the business object is created by a >> business object factory, wrap the business object in a generic >> wrapper. That wrapper would use onMM to pass all setters to the >> underlying business object, and to allow all getters to first check >> for a shadow property and if one does not exist, then pass the getter >> to the underlying business object.
>> This would allow one to keep the API of the business object, without >> having to resort to generic getters and setters, but would remove the >> previous requirement (in my implementation) of having to write a >> custom getter for any properties that need to be able to store invalid >> data. You could then use your business object directly in your view >> and would always get back the data that the user submitted, valid or >> not.
>> I haven't actually written this yet (I will), but in theory it sounds >> pretty good.
>> Comments?
>> On Fri, Sep 26, 2008 at 5:08 PM, Bob Silverberg >> <bob.silverb...@gmail.com> wrote: >>> I have yet to come up with a solution to that problem that I'm really >>> happy with. Currently my populate method, which loads data into the >>> business object and validates the datatypes, takes any invalid values >>> and stores them in "shadow" properties, from which I can retrieve them >>> when I need to display them. Unfortunately this technique requires a >>> custom getter for any properties that could have invalid values (most >>> are strings, so they don't need this functionality). Another way >>> around this is to use a generic getter that checks for the existence >>> of an invalid shadow property, and calls the standard getter if no >>> invalid value has been stored. But I'm not too keen on that either.
>>> So, my solution works, allows me to use my business object directly in >>> my view (e.g., myObj.getName()), and also allows me to redisplay any >>> invalid values entered by a user, but I'm just not that keen on the >>> implementation. I hope to one day either hear of a better >>> implementation or come up with something on my own.
>>> On Fri, Sep 26, 2008 at 4:51 PM, Kevan Stannard <ke...@stannard.net.au> wrote: >>>> Hi Brian, Mark
>>>> If a form field contains invalid data that cannot be set on a bean due to a >>>> type failure, how would you handle redisplaying that original invalid data >>>> back on the form again?
>>>> Thanks
>>>> Kevan
>>>> ________________________________
>>>> From: cfcdev@googlegroups.com [mailto:cfcdev@googlegroups.com] On Behalf Of >>>> Brian Kotek >>>> Sent: Thursday, 25 September 2008 2:23 AM >>>> To: cfcdev@googlegroups.com >>>> Subject: [CFCDEV] Re: Using object "getters" after form validation fails
>>>> I have a Validator that first attempts to set the properties on the bean (I >>>> use a Transfer object that has been cloned so that the updates don't affect >>>> the real object until it is saved, but this could be done manually as well). >>>> If any properties fail to be set (argument type failure), I record those as >>>> validation errors and then move on. After the properties are set I run a >>>> validation on them to ensure that they conform to my rules (unique value, >>>> between two numbers, required, greater than/less than, etc.) and capture >>>> those as well. Only if the validator has no errors at this point do I save >>>> the object. So you don't have to type your arguments to any, you can just >>>> capture setter failures and treat them like any other validation failure.
>>>> On Wed, Sep 24, 2008 at 9:11 AM, Kevan Stannard <ke...@stannard.net.au> >>>> wrote:
>>>> Validation discussions frequently bring up the concept of populating beans >>>> with potentially invalid data then calling a bean.validate() function, but >>>> something doesn't quite feel right about it for me.
>>>> If I have a date field in my bean, then I would like it to be a real date >>>> value (or an empty string meaning null), or if I have a numeric field in my >>>> bean then I want it to be a real numeric value. Allowing them to be anything >>>> entered by a user just doesn't feel right - but that is just where my head >>>> is at right now.
All the techniques presented here are quite intelligent and elegant but I want to throw out an idea. Whether someone uses a helper component, shadow properties or a validator, at the root there is always a need for some sort of USER api to store and manage the data. Is that not the purpose of having a USER class to begin with? To have a definition of an api from which many different instances for all types of purposes can be created? It *feels* like if 99% of an interface needs to be duplicated, then the class definition is too tightly coupled to a specific implementation and that one would be better off dumbing down the original class in favor of more composition/inheritance for the added functionality. To go back to the original example, Michael instantiated one instance of the USER class to store the logged-in user's information. Later on, he may instantiate more user objects to display query results or show someone's manager. They all share a common api but serve very different purposes with their own set of unique rules and constraints to follow. So why not just have another instance that is specifically designed to handle dirty data for validation?
The way I would solve the problem most closely resembles Peter's technique. I would have a LOGINUSER stored in session (for things like displaying their name at the top of the site) - and if someone wanted to edit that USER, I would create a new instance specifically for that unique purpose. That new instance might interact with my session instance (to populate itself perhaps), but it is still a separate special instance whose surrounding code is specifically designed to handle and expect potentially dirty data. So the form that is being used for editing, would only interact with that instance. It would display its contents, edit its contents and so forth, with no fear of that spreading to other parts of the site. Only once the entire editing process is complete would I update the SESSION.LOGINUSER instance with the new data.
That's why I am not a huge fan of shadow properties even though they do provide a lot of elegance in certain cases - there's too much duplication. It *almost* makes more sense to compose a USER object within itself - one clean and one dirty.
Caveat: I understand this wouldn't work out as nicely with transfer for reasons mentioned before.
What do you think?
Baz
On Thu, Oct 9, 2008 at 5:56 PM, Bob Silverberg <bob.silverb...@gmail.com>wrote:
> I tried it and it worked like a charm. In fact, I have incorporated > it into a "validations framework" that I've been working on for the > past several weeks. I will be discussing and documenting the > framework on my blog over the next while, and hope to have a demo up > any day now. So far I've just written an introductory post about the > goals of the framework. If you're interested you can find that post > here:
> On Thu, Oct 9, 2008 at 2:59 PM, Dan O'Keefe <dan.oke...@gmail.com> wrote:
> > Bob,
> > Was wondering if you gave this idea a spin and have prototyped it - > > and if so, did it work as expected for you.
> > Thanks,
> > Dan
> > On Thu, Oct 2, 2008 at 9:31 AM, Bob Silverberg <bob.silverb...@gmail.com> > wrote:
> >> I spent some time discussing this with Paul Marcotte last week and we > >> came up with an idea that I think is similar to what Brian was > >> suggesting. Here's what we came up with:
> >> Keep business object exactly as it is, with typed getters and setters. > >> Include the "shadow property" logic to store invalid data that cannot > >> be stored by a setter. As the business object is created by a > >> business object factory, wrap the business object in a generic > >> wrapper. That wrapper would use onMM to pass all setters to the > >> underlying business object, and to allow all getters to first check > >> for a shadow property and if one does not exist, then pass the getter > >> to the underlying business object.
> >> This would allow one to keep the API of the business object, without > >> having to resort to generic getters and setters, but would remove the > >> previous requirement (in my implementation) of having to write a > >> custom getter for any properties that need to be able to store invalid > >> data. You could then use your business object directly in your view > >> and would always get back the data that the user submitted, valid or > >> not.
> >> I haven't actually written this yet (I will), but in theory it sounds > >> pretty good.
> >> Comments?
> >> On Fri, Sep 26, 2008 at 5:08 PM, Bob Silverberg > >> <bob.silverb...@gmail.com> wrote: > >>> I have yet to come up with a solution to that problem that I'm really > >>> happy with. Currently my populate method, which loads data into the > >>> business object and validates the datatypes, takes any invalid values > >>> and stores them in "shadow" properties, from which I can retrieve them > >>> when I need to display them. Unfortunately this technique requires a > >>> custom getter for any properties that could have invalid values (most > >>> are strings, so they don't need this functionality). Another way > >>> around this is to use a generic getter that checks for the existence > >>> of an invalid shadow property, and calls the standard getter if no > >>> invalid value has been stored. But I'm not too keen on that either.
> >>> So, my solution works, allows me to use my business object directly in > >>> my view (e.g., myObj.getName()), and also allows me to redisplay any > >>> invalid values entered by a user, but I'm just not that keen on the > >>> implementation. I hope to one day either hear of a better > >>> implementation or come up with something on my own.
> >>> On Fri, Sep 26, 2008 at 4:51 PM, Kevan Stannard <ke...@stannard.net.au> > wrote: > >>>> Hi Brian, Mark
> >>>> If a form field contains invalid data that cannot be set on a bean due > to a > >>>> type failure, how would you handle redisplaying that original invalid > data > >>>> back on the form again?
> >>>> Thanks
> >>>> Kevan
> >>>> ________________________________
> >>>> From: cfcdev@googlegroups.com [mailto:cfcdev@googlegroups.com] On > Behalf Of > >>>> Brian Kotek > >>>> Sent: Thursday, 25 September 2008 2:23 AM > >>>> To: cfcdev@googlegroups.com > >>>> Subject: [CFCDEV] Re: Using object "getters" after form validation > fails
> >>>> I have a Validator that first attempts to set the properties on the > bean (I > >>>> use a Transfer object that has been cloned so that the updates don't > affect > >>>> the real object until it is saved, but this could be done manually as > well). > >>>> If any properties fail to be set (argument type failure), I record > those as > >>>> validation errors and then move on. After the properties are set I run > a > >>>> validation on them to ensure that they conform to my rules (unique > value, > >>>> between two numbers, required, greater than/less than, etc.) and > capture > >>>> those as well. Only if the validator has no errors at this point do I > save > >>>> the object. So you don't have to type your arguments to any, you can > just > >>>> capture setter failures and treat them like any other validation > failure.
> >>>> On Wed, Sep 24, 2008 at 9:11 AM, Kevan Stannard < > ke...@stannard.net.au> > >>>> wrote:
> >>>> Validation discussions frequently bring up the concept of populating > beans > >>>> with potentially invalid data then calling a bean.validate() function, > but > >>>> something doesn't quite feel right about it for me.
> >>>> If I have a date field in my bean, then I would like it to be a real > date > >>>> value (or an empty string meaning null), or if I have a numeric field > in my > >>>> bean then I want it to be a real numeric value. Allowing them to be > anything > >>>> entered by a user just doesn't feel right - but that is just where my > head > >>>> is at right now.
Right, this is what I typically do, so that I end up with an error object that contains not only type cast failures but validation rule failures as well. The only catch here is that for things that outright fail validation checks, the cloned object that repopulates the form doesn't have a value to redisplay to the user. Since typically cast failures are limited to things like dates or numbers, I check these using JavaScript or have the user make the choice from a select box or something like that. If you don't perform client-side checks, or the user disables JavaScript, it does mean that on rare occasions the redisplayed for will not be showing what the user entered for certain fields (i.e. if they enter letters for a date, that field is just empty when the form redisplays. The error message is there to explain the problem but the value they entered isn't.) Some people will say this is unacceptable for usability reasons but since the alternative is shadowing the properties with untyped functions, or manually building a separate object, I'm willing to accept this small issue. If it's really, really a problem you can disable type checking in the CF admin and let the validation catch the error instead. As far as I'm concerned, if the user disables JavaScript and enters "aaa" into a date field, it's just too bad that the redisplayed form doesn't show "aaa" in that date field. The validation error message tells them about the problem, and to me having "aaa" show up in the form again is just an invitation for the user to submit the bad data again.
On Wed, Oct 8, 2008 at 9:26 AM, Dan O'Keefe <dan.oke...@gmail.com> wrote:
> Brian,
> Just to confirm, you clone a copy of the transfer object and then > attempt to set each of the properties with a <cftry><cfcatch> around > it so if any of the properties fails to set you note it, and if no > errors were detected you make a second pass at each property for the > additional rules? If any errors were detected on either pass you > return the cloned object to the form to re-populate the form. If no > errors were detected, save the cloned transfer object, if saved > successfully, update your original object from the clone?
> Sorry if that is a little incoherent, but I want to make sure I am > following you from form submission and back to the form if errors > occur, and if not, persisting to the DB. I have read the other posts > in the group here regarding changing the type to "Any" or not and I > think that is what you were addressing here. Also the issue of making > sure the session scope object in in sync as to what is in the DB.
> Thanks,
> Dan
> On Wed, Sep 24, 2008 at 12:22 PM, Brian Kotek <brian...@gmail.com> wrote: > > I have a Validator that first attempts to set the properties on the bean > (I > > use a Transfer object that has been cloned so that the updates don't > affect > > the real object until it is saved, but this could be done manually as > well). > > If any properties fail to be set (argument type failure), I record those > as > > validation errors and then move on. After the properties are set I run a > > validation on them to ensure that they conform to my rules (unique value, > > between two numbers, required, greater than/less than, etc.) and capture > > those as well. Only if the validator has no errors at this point do I > save > > the object. So you don't have to type your arguments to any, you can just > > capture setter failures and treat them like any other validation failure.
> As far as I'm concerned, if the user disables JavaScript and enters "aaa" > into a date field, it's just too bad that the redisplayed form doesn't show > "aaa" in that date field. The validation error message tells them about the > problem, and to me having "aaa" show up in the form again is just an > invitation for the user to submit the bad data again.
Could not agree more. I am all for usability but at some point, have to put some ownership on the user to have a clue. Thanks for the verification. I am going to model out a test case and try it.
Whatever solution we decide to implement (server or client) should never affect the user experience, and data that does not validate should always be displayed in its original field. In the context of your example, a European user might very well enter 31/12/2008 as a date. That would not be clueless.
Jean
What if a European user enters 31/12/2008 for a date?
On Mon, Oct 13, 2008 at 5:35 AM, Dan O'Keefe <dan.oke...@gmail.com> wrote:
> > As far as I'm concerned, if the user disables JavaScript and enters "aaa" > > into a date field, it's just too bad that the redisplayed form doesn't > show > > "aaa" in that date field. The validation error message tells them about > the > > problem, and to me having "aaa" show up in the form again is just an > > invitation for the user to submit the bad data again.
> Could not agree more. I am all for usability but at some point, have > to put some ownership on the user to have a clue. Thanks for the > verification. I am going to model out a test case and try it.
> Whatever solution we decide to implement (server or client) should never > affect the user experience, and data that does not validate should always be > displayed in its original field. In the context of your example, a European > user might very well enter 31/12/2008 as a date. That would not be clueless.
> Jean
> What if a European user enters 31/12/2008 for a date?
> On Mon, Oct 13, 2008 at 5:35 AM, Dan O'Keefe <dan.oke...@gmail.com> wrote:
>> > As far as I'm concerned, if the user disables JavaScript and enters >> > "aaa" >> > into a date field, it's just too bad that the redisplayed form doesn't >> show >> > "aaa" in that date field. The validation error message tells them about >> the >> > problem, and to me having "aaa" show up in the form again is just an >> > invitation for the user to submit the bad data again.
>> Could not agree more. I am all for usability but at some point, have >> to put some ownership on the user to have a clue. Thanks for the >> verification. I am going to model out a test case and try it.